package web.sms.mvc.service.impl;

import cn.palerock.core.shiro.useradmin.auditor.UserAuditor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import web.sms.core.exception.ServiceException;
import web.sms.mvc.constant.WorkerGroupConstant;
import web.sms.mvc.dao.WorkerGroupMapper;
import web.sms.mvc.entity.pojo.WorkerCaptain;
import web.sms.mvc.entity.WorkerGroup;
import web.sms.mvc.entity.WorkerGroupKey;
import web.sms.mvc.service.UserService;
import web.sms.mvc.service.WorkerGroupService;

import java.util.Date;
import java.util.List;

/**
 * 时间： 2017/12/18
 *
 * @author Eoly
 */
@Service
public class WorkerGroupServiceImpl implements WorkerGroupService {

    private final WorkerGroupMapper workerGroupMapper;
    private final UserService userService;
    private final UserAuditor userAuditor;

    @Autowired
    public WorkerGroupServiceImpl(WorkerGroupMapper workerGroupMapper, UserService userService, UserAuditor userAuditor) {
        this.workerGroupMapper = workerGroupMapper;
        this.userService = userService;
        this.userAuditor = userAuditor;
    }

    @Override
    public Integer addNewWorkerGroup(List<Integer> userIdList, Integer leaderId, Integer processId) {
        if (leaderId == null) {
            throw new ServiceException(WorkerGroupConstant.WORKER_NOT_EXIST);
        }
        if (processId == null) {
            throw new ServiceException(WorkerGroupConstant.PROCESS_NOT_EXIST);
        }
        userAuditor.checkPerms("worker:admin|worker:add");
        // 查询组长工人信息并检查
        boolean isWorker = userService.hasRole(leaderId, "worker",
                WorkerGroupConstant.WORKER_NOT_EXIST);
        if (!isWorker) {
            throw new ServiceException(WorkerGroupConstant.USER_NOT_HAS_WORKER_ROLE);
        }
        // 添加工人组，并将组长作为第一个工人
        WorkerGroup workerGroup = new WorkerGroup();
        workerGroup.setWorkerId(leaderId);
        workerGroup.setWorkerIsLeader(Boolean.TRUE);
        workerGroup.setWorkerProcessId(processId);
        Integer workerGroupId = addWorkerGroupWithoutChecking(workerGroup);
        // 遍历组员并添加
        for (Integer workerId : userIdList) {
            // 不添加组长id
            if (!leaderId.equals(workerId) && workerId != null) {
                this.addToWorkerGroup(workerId, workerGroupId);
            }
        }
        return workerGroupId;
    }

    @Override
    public void addToWorkerGroup(Integer workerId, Integer workerGroupId) {
        if (workerGroupId == null || workerId == null) {
            throw new ServiceException(WorkerGroupConstant.EMPTY_GROUP_ID_OR_WORKER_ID);
        }
        userAuditor.checkPerms("worker:admin|worker:add");
        // 查询工人并检查
        boolean isWorker = userService.hasRole(workerId, "worker",
                WorkerGroupConstant.WORKER_NOT_EXIST);
        if (!isWorker) {
            throw new ServiceException(WorkerGroupConstant.USER_NOT_HAS_WORKER_ROLE);
        }
        // 添加工人组
        WorkerGroup workerGroup = new WorkerGroup();
        workerGroup.setWorkerId(workerId);
        workerGroup.setWorkerGroupId(workerGroupId);
        addWorkerGroupWithoutChecking(workerGroup);
    }

    @Override
    public void addToWorkerGroup(Integer workerGroupId, List<Integer> userIdList) {
        userAuditor.checkPerms("worker:admin|worker:add");
        for (Integer workerId : userIdList) {
            addToWorkerGroup(workerId, workerGroupId);
        }
    }

    @Override
    public void makeWorkerToBeLeaderInWorkerGroup(WorkerGroupKey workerGroupKey) {
        // 获取所有属于该组的实体
        List<WorkerGroup> workerGroups = workerGroupMapper.selectWorkerGroupByGroupId(
                workerGroupKey.getWorkerGroupId());
        userAuditor.checkPerms("worker:admin|worker:edit");
        if (workerGroups == null || workerGroups.size() <= 0) {
            // 指定的小组id不存在
            throw new ServiceException(WorkerGroupConstant.GROUP_ID_IS_NOT_EXIST_ERROR,
                    workerGroupKey.getWorkerGroupId());
        }
        boolean hasChooseWorker = false;
        Integer processId = null;
        for (WorkerGroup workerGroup : workerGroups) {
            if (workerGroupKey.getWorkerId().equals(workerGroup.getWorkerId())) {
                hasChooseWorker = true;
                continue;
            }
            // 取消团队中其它组长的位置
            if (workerGroup.getWorkerIsLeader()) {
                workerGroup.setWorkerIsLeader(Boolean.FALSE);
                processId = workerGroup.getWorkerProcessId();
                this.editWorkerGroupWithoutChecking(workerGroup);
            }
        }
        if (!hasChooseWorker) {
            // 指定小组没有欲指定为组长的工人，此处异常会回滚上面取消组长的操作
            throw new ServiceException(WorkerGroupConstant.WORKER_IS_NOT_IN_THIS_GROUP,
                    workerGroupKey.getWorkerId(), workerGroupKey.getWorkerGroupId());
        }
        if (processId == null) {
            // 若队长没有指定流程id，发生错误
            throw new ServiceException(WorkerGroupConstant.LEADER_HAS_NOT_PROCESS_ID);
        }
        // 将选择工人设置为组长
        WorkerGroup workerGroup = new WorkerGroup(workerGroupKey, Boolean.TRUE);
        this.editWorkerGroupWithoutChecking(workerGroup);
    }

    @Override
    public List<WorkerCaptain> findAllCaptain() {
        List<WorkerCaptain> workerCaptains = workerGroupMapper.selectAllGroupCaptains();
        if (workerCaptains == null || workerCaptains.size() == 0) {
            throw new ServiceException(WorkerGroupConstant.NOT_EXIST_CAPTAINS);
        }
        return workerCaptains;
    }

    @Override
    public List<WorkerCaptain> findCaptainsByProcessId(Integer processId) {
        if (processId == null) {
            throw new ServiceException(WorkerGroupConstant.PROCESS_NOT_EXIST);
        }
        List<WorkerCaptain> workerCaptains = workerGroupMapper
                .selectAllGroupCaptainsByProcessId(processId);
        if (workerCaptains == null || workerCaptains.size() == 0) {
            throw new ServiceException(WorkerGroupConstant.NOT_EXIST_CAPTAINS);
        }
        return workerCaptains;
    }

    @Override
    public WorkerCaptain findCaptainByGroupId(Integer groupId) {
        WorkerCaptain workerCaptain = workerGroupMapper.selectWorkerCaptainByGroupId(groupId);
        if (workerCaptain == null) {
            throw new ServiceException(WorkerGroupConstant.GROUP_OR_LEADER_NOT_EXIST);
        }
        return workerCaptain;
    }

    @Override
    public WorkerCaptain findCaptainDetailWithinTime(Integer groupId, Date startTime, Date endTime) {
        userAuditor.checkPerms("order:admin|order:find");
        WorkerCaptain workerCaptain = workerGroupMapper.selectWorkerCaptainWithinTime(
                groupId,
                startTime,
                endTime,
                true
        );
        if (workerCaptain == null) {
            throw new ServiceException(WorkerGroupConstant.GROUP_OR_LEADER_NOT_EXIST);
        }
        // 手动赋予工单总数
        if (workerCaptain.getGroupOrderInfo() != null) {
            workerCaptain.getGroupOrderInfo().setOrderNumSum(
                    workerCaptain.getGroupOrderInfo().getOrders().size()
            );
        }
        return workerCaptain;
    }

    @Override
    public List<WorkerGroup> findGroupInfo(Integer groupId) {
        return workerGroupMapper.selectWorkerGroupInfoByGroupId(groupId);
    }

    /**
     * 私有方法
     * 修改工人组属性并且不进行角色和其它检测
     *
     * @param workerGroup 工人组实体
     */
    private void editWorkerGroupWithoutChecking(WorkerGroup workerGroup) {
        int result = workerGroupMapper.updateByPrimaryKeySelective(workerGroup);
        if (result < 1) {
            throw new ServiceException(WorkerGroupConstant.SERVER_RUN_SQL_FAILURE,
                    WorkerGroupConstant.EDITING_GROUP_FAILURE);
        }
    }

    /**
     * 私有方法
     * 添加工人组属性并且不进行角色和其它检测
     *
     * @param workerGroup 工人组实体
     */
    private Integer addWorkerGroupWithoutChecking(WorkerGroup workerGroup) {
        int result = workerGroupMapper.insertSelective(workerGroup);
        if (result < 1) {
            throw new ServiceException(WorkerGroupConstant.SERVER_RUN_SQL_FAILURE,
                    WorkerGroupConstant.EDITING_GROUP_FAILURE);
        }
        return workerGroup.getWorkerGroupId();
    }
}
